package com.jy.rhin.application.registration;

import java.lang.Integer;
import java.lang.String;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import javax.xml.bind.annotation.XmlEnumValue;

import cn.org.chiss.rhin._2015.base.*;
import cn.org.chiss.rhin._2015.base.object.*;
import com.jy.api.hospital.dto.HospitalDTO;
import com.jy.api.hospital.dto.JiGouDTO;
import com.jy.api.misc.MiscAPI;
import com.jy.common.StringUtil;
import com.jy.framework.base.entity.Result;
import com.jy.rhin.config.RhinFaultSubCode;
import com.jy.rhin.facade.ws.basic.wsEntry.exception.RhinWSException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jy.api.hospital.HospitalAPI;
import com.jy.api.hospital.dto.ZhiGongDetailDTO;
import com.jy.framework.base.entity.Page;

import cn.org.chiss.rhin._2015.registration.organization.OrganizationFeed;
import cn.org.chiss.rhin._2015.registration.organization.OrganizationFeedResponse;
import cn.org.chiss.rhin._2015.registration.organization.OrganizationQueryRequest;
import cn.org.chiss.rhin._2015.registration.organization.OrganizationQueryResponseMessage;
import cn.org.chiss.rhin._2015.registration.organization.PractitionerFeedResponse;
import cn.org.chiss.rhin._2015.registration.organization.PractitionerQuery;
import cn.org.chiss.rhin._2015.registration.organization.PractitionerQueryResponse;

@Service
public class OrganizationService {

    @Autowired
    private HospitalAPI hospitalApi;
    @Autowired
    private MiscAPI miscAPI;

    public OrganizationFeedResponse organizationFeed(OrganizationFeed message) {
        Organization organization = new Organization();
        OrganizationFeedResponse resp;
        try {
            organization.setIdentifier(message.getOrganization().getIdentifier());
            JiGouDTO jiGouDTO = toHospital(message);
            Result<String> result = hospitalApi.huLianHTJG(jiGouDTO);
            if (result.isSuccess()) {
                resp = new OrganizationFeedResponse();
                //Identifier i = new Identifier();
                //	ID id = new ID();
                //	id.setValue(String.valueOf(result.getData()));
                //	id.setValue("1");
                //	i.setValue(id);
                resp.setMasterIdentifier(new Identifier().setValue(new ID().setValue(String.valueOf(result.getData()))));
                URI uri = new URI();
                uri.setValue("2.16.156.10011.1.5");
                resp.getMasterIdentifier().setSystem(uri);
                return resp;
            }
            throw new RuntimeException("添加机构失败:"+result.getMsg());
        } catch (Exception e) {
            throw new RhinWSException(RhinFaultSubCode.OrganizationInformationIncoupleteFault);
        }
    }

    private JiGouDTO toHospital(OrganizationFeed message) {
        JiGouDTO z = new JiGouDTO();
        JSONArray array = new JSONArray();
        array.add(getBaseInfo("数据来源", "HIS"));
        array.add(getBaseInfo("标识符", message.getOrganization().getIdentifier().get(0).getValue().getValue()));
        array.add(getBaseInfo("机构名称", message.getOrganization().getName().get(0).getValue()));
        array.add(getBaseInfo("行政区划", message.getOrganization().getAddress().getState().getValue() + "-" + message.getOrganization().getAddress().getCity().getValue() + "-" + message.getOrganization().getAddress().getDistrict().getValue()));
        array.add(getBaseInfo("机构性质", "2"));
        array.add(getBaseInfo("机构级别", "90"));
        array.add(getBaseInfo("机构等次", "其他"));
        array.add(getBaseInfo("医疗资源分类", "A"));
        array.add(getBaseInfo("联系电话", String.valueOf(message.getOrganization().getTelecom().getValue().getValue())));
        //array.add(getBaseInfo("经济类型", String.valueOf(message.getOrganization().getHealthcareFacilityTypeCode().getText())));
        z.setExtInfo(array.toJSONString());
        return z;
    }

    private static String getStatusCodeValue(ObjectStatus objectStatus) {
        if (Objects.nonNull(objectStatus) && Objects.nonNull(objectStatus.getValue())) {
            Class<ObjectStatusPrimitive> primitiveClass = ObjectStatusPrimitive.class;
            Field[] fields = primitiveClass.getFields();
            for (Field field : fields) {
                String name = objectStatus.getValue().name();
                if (name.equals(field.getName())) {
                    return field.getAnnotation(XmlEnumValue.class).value();
                }
            }
        }
        return "";
    }

    private JSONObject getBaseInfo(String key, String value) {
        JSONObject h = new JSONObject();
        h.put("group", "基本信息");
        h.put("label", key);
        h.put("value", value);
        return h;
    }

    public OrganizationQueryResponseMessage organizationQuery(OrganizationQueryRequest OrganizationQueryRequest) {
        String id = null;
        String jiGouFL = null;
        String jiGouFLMC = null;
        String jiGouFLFS = null;
        String status = null;
        String hospitalId = null;
        String hospitalName = null;
        String address = null;
        String mobile = null;
        if (OrganizationQueryRequest.getAdhocQuery() != null && !ObjectUtils.isEmpty(OrganizationQueryRequest.getAdhocQuery().getSlot())) {
            for (Slot s : OrganizationQueryRequest.getAdhocQuery().getSlot()) {
                if ("$organizationID".equals(s.getName().getValue())) {
                    hospitalId = s.getValueList().getValue().get(0).getValue();
                }
                if ("$organizationStatusCode".equals(s.getName().getValue())) {
                    status = s.getValueList().getValue().get(0).getValue();
                }
                if ("$organizationName".equals(s.getName().getValue())) {
                    hospitalName = s.getValueList().getValue().get(0).getValue();
                }
                if ("$organizationAddress".equals(s.getName().getValue())) {
                    address = s.getValueList().getValue().get(0).getValue();
                }
                if ("$organizationTelecom".equals(s.getName().getValue())) {
                    mobile = s.getValueList().getValue().get(0).getValue();
                }
                if ("$organizationClassCode".equals(s.getName().getValue())) {
                    jiGouFL = s.getValueList().getValue().get(0).getValue();
                }
                if ("$organizationClassName".equals(s.getName().getValue())) {
                    jiGouFLMC = s.getValueList().getValue().get(0).getValue();
                }
                if ("$organizationClassSystem".equals(s.getName().getValue())) {
                    jiGouFLFS = s.getValueList().getValue().get(0).getValue();
                }
                if ("$organizationIdentifier".equals(s.getName().getValue())) {
                    hospitalId = s.getValueList().getValue().get(0).getValue();
                }
            }
        }
//		if(OrganizationQueryRequest.getAdhocQuery().getId().getValue()!=null){
//			id = OrganizationQueryRequest.getAdhocQuery().getId().getValue();
//		}
        Integer from = OrganizationQueryRequest.getFrom();
        Integer maxCount = OrganizationQueryRequest.getMaxCount();
        Page<JiGouDTO> page = hospitalApi.pageJiGouRhin(id, hospitalId, hospitalName, status, jiGouFL, jiGouFLMC, jiGouFLFS, address, mobile, from, maxCount).getData();
        if (hospitalId != null && page.getRecords().size() == 0) {
            throw new RhinWSException(RhinFaultSubCode.QueryParamIncorrectFault);
        }
        return jiGouPageToPractitionerQueryResponse(page, OrganizationQueryRequest);
    }


    private OrganizationQueryResponseMessage jiGouPageToPractitionerQueryResponse(Page<JiGouDTO> page, OrganizationQueryRequest message) {
        OrganizationQueryResponseMessage resp = new OrganizationQueryResponseMessage();
        resp.setFrom(new cn.org.chiss.rhin._2015.base.Integer().setValue(message.getFrom()));
        resp.setCount(new cn.org.chiss.rhin._2015.base.Integer().setValue(message.getMaxCount()));
        resp.setTotalCount(new cn.org.chiss.rhin._2015.base.Integer().setValue(0));
        if (page != null) {
            resp.setTotalCount(new cn.org.chiss.rhin._2015.base.Integer().setValue((int) page.getTotal()));
            if (!ObjectUtils.isEmpty(page.getRecords())) {
                List<Organization> organization = new ArrayList<Organization>();
                for (JiGouDTO z : page.getRecords()) {
                    Organization p = new Organization();
                    p.setAddress(new Address().setText(new cn.org.chiss.rhin._2015.base.String().setValue(z.getAddress()))
                            .setState(new cn.org.chiss.rhin._2015.base.String().setValue(getXZQHMC(z.getProvince())))
                            .setCity(new cn.org.chiss.rhin._2015.base.String().setValue(getXZQHMC(z.getCity())))
                            .setDistrict(new cn.org.chiss.rhin._2015.base.String().setValue(getXZQHMC(z.getDistrict())))
                            .setTown(new cn.org.chiss.rhin._2015.base.String().setValue(getXZQHMC(z.getCommunity())))
                            .setStreet(new cn.org.chiss.rhin._2015.base.String().setValue(getXZQHMC(z.getStreet()))));
                    p.setIdentifier(getList(Identifier.class, new Identifier().setValue(new ID().setValue(z.getHospitalId())).setSystem(new URI().setValue(z.getHospitalId()))));
                    p.setName(getList(cn.org.chiss.rhin._2015.base.String.class, new cn.org.chiss.rhin._2015.base.String().setValue(z.getJiGouName())));
                    p.setStatusCode(new ObjectStatus().setValue(ObjectStatusPrimitive.ACTIVE));
                    organization.add(p);
                }
                resp.setOrganization(organization);
            }

        }
        return resp;
    }

    public PractitionerFeedResponse practitionerFeed(Practitioner practitioner) {
        PractitionerFeedResponse resp;
        try {
            ZhiGongDetailDTO zhiGongDetailDTO = toZhiGongDetailDTO(practitioner);
            Result<String> result = hospitalApi.huLianHTZG(zhiGongDetailDTO);
            if (result.isSuccess()) {
                resp = new PractitionerFeedResponse();
                resp.setMasterIdentifer(new Identifier().setValue(new ID().setValue(String.valueOf(result.getData()))));
                URI uri = new URI();
                uri.setValue(String.valueOf(result.getData()));
                resp.getMasterIdentifier().setSystem(uri);
                return resp;
            }
            throw new RhinWSException(RhinFaultSubCode.PractitionerInformationIncompleteFault);
        } catch (Exception e) {
            throw new RhinWSException(RhinFaultSubCode.PractitionerInformationIncompleteFault);
        }
    }

    private ZhiGongDetailDTO toZhiGongDetailDTO(Practitioner practitioner) {
        ZhiGongDetailDTO z = new ZhiGongDetailDTO();
        JSONArray array = new JSONArray();
        array.add(getBaseInfo("数据来源", "HIS"));
        array.add(getBaseInfo("标识符", practitioner.getIdentifier().get(0).getValue().getValue()));
        array.add(getBaseInfo("机构标识符", practitioner.getPracticeOrganization().getPartOf().getIdentifier().get(0).getValue().getValue()));
        array.add(getBaseInfo("科室标识符", practitioner.getPracticeOrganization().getIdentifier().get(0).getValue().getValue()));
        array.add(getBaseInfo("人员姓名", practitioner.getAssignedPerson().getName().get(0).getValue()));
        array.add(getBaseInfo("性别", practitioner.getAssignedPerson().getGender().getValue()));
        array.add(getBaseInfo("出生日期", practitioner.getAssignedPerson().getBirthTime().getValue()));
        array.add(getBaseInfo("联系电话", practitioner.getAssignedPerson().getTelecom().get(0).getValue().getValue()));
        array.add(getBaseInfo("职工代码", practitioner.getIdentifier().get(0).getValue().getValue()));
        array.add(getBaseInfo("职务代码", practitioner.getDuty().get(0).getCode().getValue()));
        array.add(getBaseInfo("职称代码", practitioner.getProfessionalTitle().get(0).getCode().getValue()));
        z.setExtInfo(array.toJSONString());
        return z;
    }

    private String getXZQHMC(String xzqhdm) {
        if (xzqhdm == null || "".equals(xzqhdm)) {
            return null;
        }
        return miscAPI.getQuHuaDMByDM(xzqhdm).getData().getMingCheng();
    }

    public PractitionerQueryResponse practitionerQuery(PractitionerQuery message) {
        Page<ZhiGongDetailDTO> page = getZhiGongXX(message);
        if (page != null && page.getRecords().size() == 0) {
            throw new RhinWSException(RhinFaultSubCode.PractitionerNotFoundFault);
        }
        return zhiGongPageToPractitionerQueryResponse(page, message);
    }

    private Page<ZhiGongDetailDTO> getZhiGongXX(PractitionerQuery message) {
        String zgGh = null;
        String status = null;
        String name = null;
        String zwdm = null;
        String zcDm = null;
        String hospitalId = null;
        if (message.getAdhocQuery() != null && !ObjectUtils.isEmpty(message.getAdhocQuery().getSlot())) {
            for (Slot s : message.getAdhocQuery().getSlot()) {
                if ("$practitionerID".equals(s.getName().getValue())) {
                    zgGh = s.getValueList().getValue().get(0).getValue();
                }
                if ("$practitionerStatusCode".equals(s.getName().getValue())) {
                    status = s.getValueList().getValue().get(0).getValue();
                }
                if ("$practitionerIdentifier".equals(s.getName().getValue())) {
                    zgGh = s.getValueList().getValue().get(0).getValue();
                }
                if ("$practitionerName".equals(s.getName().getValue())) {
                    name = s.getValueList().getValue().get(0).getValue();
                }
                if ("$practitionerDutyCode".equals(s.getName().getValue())) {
                    zwdm = s.getValueList().getValue().get(0).getValue();
                }
                if ("$practitionerProfessionalCode".equals(s.getName().getValue())) {
                    zcDm = s.getValueList().getValue().get(0).getValue();
                }
                if ("$practitionerpracticeOrganizationID".equals(s.getName().getValue())) {
                    hospitalId = s.getValueList().getValue().get(0).getValue();
                }
            }
        }
        Integer from = message.getFrom().getValue();
        Integer maxCount = message.getMaxCount().getValue();
        Page<ZhiGongDetailDTO> page = hospitalApi.page4Rhin(zgGh, status, name, zwdm, zcDm, from, maxCount, hospitalId).getData();
        return page;
    }

    private PractitionerQueryResponse zhiGongPageToPractitionerQueryResponse(Page<ZhiGongDetailDTO> page, PractitionerQuery message) {
        PractitionerQueryResponse resp = new PractitionerQueryResponse();
        resp.setFrom(message.getFrom());
        resp.setCount(message.getMaxCount());
        resp.setTotalCount(new cn.org.chiss.rhin._2015.base.Integer().setValue(0));
        if (page != null) {
            resp.setTotalCount(new cn.org.chiss.rhin._2015.base.Integer().setValue((int) page.getTotal()));
            if (!ObjectUtils.isEmpty(page.getRecords())) {
                List<Practitioner> practitioner = new ArrayList<Practitioner>();
                for (ZhiGongDetailDTO z : page.getRecords()) {
                    Practitioner p = new Practitioner();
                    p.setAssignedPerson(new Person().setName(getList(HumanName.class, new HumanName().setValue(z.getZgXm())))
                            .setGender(new Code().setValue("1".equals(z.getZhiGongXB()) ? "1" : "2".equals(z.getZhiGongXB()) ? "2" : "0"))
                            .setTelecom(getList(Telecom.class, new Telecom().setValue(new cn.org.chiss.rhin._2015.base.String().setValue(z.getShouJiHao()))))
                            .setBirthTime(new Date().setValue(z.getChuShengRQ())));
                    p.setDuty(getList(Coding.class, new Coding().setCode(new Code().setValue(z.getZwDm()))));
                    p.setIdentifier(getList(Identifier.class, new Identifier().setValue(new ID().setValue(z.getZgGh())).setSystem(new URI().setValue(z.getZgGh()))));
                    Organization o = new Organization().setIdentifier(getList(Identifier.class, new Identifier().setValue(new ID().setValue(StringUtil.isEmpty(z.getKsdm()) ? z.getHospitalId() : z.getKsdm())).setSystem(new URI().setValue(StringUtil.isEmpty(z.getKsdm()) ? z.getHospitalId() : z.getKsdm()))));
                    o.setName(getList(cn.org.chiss.rhin._2015.base.String.class, new cn.org.chiss.rhin._2015.base.String().setValue(z.getKsmc())));
                    o.setStatusCode(new ObjectStatus().setValue(ObjectStatusPrimitive.ACTIVE));
                    HospitalDTO hospitalInfo = hospitalApi.info(z.getHospitalId()).getData();
                    o.setPracticeSettingCode(getPracticeSetting(hospitalInfo));
                    o.setAddress(new Address().setAdministrativeDivision(new cn.org.chiss.rhin._2015.base.String().setValue("440300")));
                    o.setPartOf(getPatOf(hospitalInfo));
                    p.setPracticeOrganization(o);
                    p.setProfessionalTitle(getList(Coding.class, new Coding().setCode(new Code().setValue(z.getZcDm()))));
                    p.setStatusCode(new ObjectStatus().setValue(ObjectStatusPrimitive.ACTIVE));
                    CodeableConcept codeableConcept = new CodeableConcept();
                    Coding coding = new Coding();
                    coding.setCode(new Code().setValue("123"));
                    coding.setSystem(new URI().setValue("454"));
                    codeableConcept.setCoding(getList(Coding.class, coding));
                    p.setClassCode(codeableConcept);
                    practitioner.add(p);
                }
                resp.setPractitioner(practitioner);
            }

        }
        return resp;
    }

    private Organization getPatOf(HospitalDTO hospitalInfo) {
        Organization oz = new Organization();
        oz.setIdentifier(getList(Identifier.class, new Identifier().setValue(new ID().setValue(hospitalInfo.getHospitalId()))
                .setSystem(new URI().setValue(hospitalInfo.getHospitalId()))));
        oz.setStatusCode(new ObjectStatus().setValue(ObjectStatusPrimitive.ACTIVE));
        oz.setName(getList(cn.org.chiss.rhin._2015.base.String.class, new cn.org.chiss.rhin._2015.base.String().setValue(hospitalInfo.getName())));
        oz.setPracticeSettingCode(getPracticeSetting(hospitalInfo));
        return oz;
    }

    private CodeableConcept getPracticeSetting(HospitalDTO hospitalInfo) {
        CodeableConcept cc = new CodeableConcept();
        String yiYuanXZ = "";
        String yiYuanMC = "";
        String yiYuanDM = "";
        if (1 == hospitalInfo.getYiYuanJYXZ()) {
            yiYuanXZ = "2.16.156.10011.2.3.4.6";
            yiYuanMC = "综合医院";
            yiYuanDM = "A100";
        } else if (2 == hospitalInfo.getYiYuanJYXZ()) {
            yiYuanXZ = "2.16.156.10011.2.3.4.6";
            yiYuanMC = "中医专科医院";
            yiYuanDM = "A220";

        }
        Coding coding = new Coding().setCode(new Code().setValue(yiYuanDM))
                .setDisplay(new cn.org.chiss.rhin._2015.base.String()
                        .setValue("经济类型代码")).setSystem(new URI()
                        .setValue(yiYuanXZ)).setSystemName(new cn.org.chiss.rhin._2015.base.String().setValue(yiYuanMC))
                .setVersion(new cn.org.chiss.rhin._2015.base.String().setValue("1"));
        cc.setCoding(getList(Coding.class, coding));
        cc.setText(new cn.org.chiss.rhin._2015.base.String().setValue(yiYuanDM));
        return cc;
    }

    private <T> List<T> getList(Class<T> c, T b) {
        ArrayList<T> list = new ArrayList<T>();
        list.add(b);
        return list;
    }


}
